home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-11-04 | 36.1 KB | 1,487 lines | [TEXT/NISI] |
- \ v2.14 IOTASK
- \ Release 8/21/88
-
- \ v2.14 Fixed problems with empty menubar code in (RUN-DRAG) and (RUN-CONTENT) and
- \ altered HandleDialog to use EVENT-RECORD message on Activate and Update events.
- \ Altered (RUN-DRAG) to correctly handle command-key drags.
-
- \ I/O Task High Level Code
- \ Copyright 1987-1988 Palo Alto Shipping Company
-
-
- \ ========================================================================
- \ ========================================================================
- \ ========================================================================
-
- \ Well here it is !
- \ The I/O Task Revealed:
-
- \ The I/O task is the task in the Mach2 environment which handles all
- \ I/O for the Mach2 task and all user created tasks. Since I/O on the
- \ Macintosh involves the handling of events, the "I/O task" in Mach2 is
- \ really the same as the "event loop" which lies at the heart of all
- \ Macintosh applications.
-
- \ The I/O task has been brought out from the dark, mysterious
- \ depths of the Mach2 kernel. The Forth level source is available for
- \ study and soon, you will be able to create your own customized I/O
- \ task and install it in Mach2 in place of the default I/O task.
-
- \ Note: You have always been able to override
- \ individual event-handling routines with the
- \ use of the user variable/event vectoring mechanism.
- \ The ability to substitute a completely new I/O
- \ task gives you even more control over event
- \ response in your application.
-
- \ This file contains the source to the default I/O task which is
- \ used by Mach2. The original I/O task code was written in assembly
- \ language. The I/O task source in this file is the assembly->Forth
- \ translation of the original I/O task.
-
- \ A new utility word called NEW-IOTASK is being added to the FORTH
- \ vocabulary. The NEW-IOTASK utility will allow you to substitute your
- \ own version of the I/O task in place of the default version.
-
- \ The use of NEW-IOTASK will be similar to the use of NEW-SEGMENT .
- \ You will load your new I/O task code and then execute NEW-IOTASK.
- \ NEW-IOTASK will remove the current I/O task code segment (#2).
- \ All code in the current user code segment will be incorporated into
- \ the new I/O task code segment.
-
- \ A successful replacement I/O task must include the following routines
- \ (they must have these names):
-
- \ (IOTASK)
- \ (EVENT-TABLE)
- \ (HandleEvent)
- \ (HandleDialog)
- \ (IOTASK)
- \ (CHECK-CONTROL)
- \ (RUN-CONTENT)
- \ (RUN-GROWBOX)
- \ (RUN-DRAG)
- \ (RUN-CLOSEBOX)
- \ (RUN-ZOOMIN)
- \ (RUN-ZOOMOUT)
- \ (RUN-ACTIVATE)
- \ (RUN-UPDATE)
-
- \ When NEW-IOTASK is executed it will check to make sure all of the
- \ above dictionary entries exist. If any are missing, NEW-IOTASK will
- \ abort.
-
-
- \ ========================================================================
- \ ========================================================================
- \ ========================================================================
-
- \ Technical note: To avoid using global variables, local
- \ variables have been used to hold rectangle data. Since
- \ a local variable can hold only 4 bytes of information,
- \ two successive local variables were required to hold a
- \ complete rectange record (2 bytes each for the top, left,
- \ bottom, and right coordinates). An example of this use
- \ of local variables is found in the (RUN-GROWBOX) routine:
-
- \ : (RUN-GROWBOX) { | wptr rightbot lefttop newwidth newheight -- }
-
- \ In this routine, "rightbot" and "lefttop" are used to
- \ hold rectangle information. To place a rectangle record in
- \ these local variables the following phrase is used:
-
- \ ScreenRect ^ lefttop 8 CMOVE
-
- \ "ScreenRect" returns the address of a rectangle record,
- \ "^ lefttop" returns the start address of an 8-byte area
- \ in the local variable stack frame which is to be used to
- \ hold the rectangle record, and "8 CMOVE" moves the
- \ rectangle record into the local variable area.
-
- \ When local variable space is allocated, the storage space
- \ for the rightmost local variables in the local variable list
- \ will be located lower in memory than the storage spaces for
- \ the leftmost local variables.
-
-
- \ ========================================================================
- \ ========================================================================
- \ ========================================================================
- CR .( Loading new I/O task code...) CR
-
- ONLY MAC
- ALSO DEVELOPMENT
- ALSO ASSEMBLER
- ALSO FORTH DEFINITIONS
-
-
- \ ===== Miscellaneous Constants ==========================================
- HEX
-
- 1 CONSTANT .TRUE.
- 0 CONSTANT .FALSE.
-
- FFFFFF86 CONSTANT screenBits \ Offset to global Quickdraw variable which
- \ holds the address of a bitmap record which
- \ describes the screen currently in use.
- 6 CONSTANT screenBounds \ Offset into a bitmap record to the bounding
- \ rectangle information.
- 08 CONSTANT portBounds \ Offset to bounding box of screen bitmap.
- 00640064 CONSTANT DiskPt
- 1 CONSTANT ActivateMask
- 100 CONSTANT CommandKeyMask
- FFFFFFFF CONSTANT EveryEvent \ Recognize every event.
-
- 10 CONSTANT portRect \ Offset to window rect in grafport.
- 6C CONSTANT windowKind \ Window type field [word].
- 8C CONSTANT controlList \ Offset to control list in a window record.
- 90 CONSTANT nextWindow \ Next window in Z-ordered list.
- 9C CONSTANT GrowFlagOffset \ Offset to Mach2 "Does this window
- \ have a growbox?" flag located past the
- \ end of a window record.
- 9E CONSTANT VBarOffset \ A Mach2-generated window with a V- or
- A2 CONSTANT HBarOffset \ H-SCROLLBAR will have either the handle
- \ to the scrollbar or a 0 at these offsets
- \ to locations just past the end of a
- \ window record.
- 08 CONSTANT CtrlRectOffset \ Offset in a Mac control record to
- \ bounding rectangle for the control.
-
- DECIMAL
- 2 CONSTANT dialogKind
- 11 CONSTANT PatBic
- 129 CONSTANT InThumb
-
-
- \ ===== Mach2 Private Global Variables ===================================
- HEX
-
- : EditHandle ( - a ) \ Address where handle to "Edit" menu
- NP 14 + \ is stored.
- ;
-
- : EmptyMenuBar ( - a ) \ Address where handle to an empty
- EVENT-RECORD 1E + \ menu is stored.
- ;
-
-
- \ ===== EVENT-RECORD Offsets =============================================
- DECIMAL
-
- 0 CONSTANT What
- 2 CONSTANT Message
- 6 CONSTANT When
- 10 CONSTANT Where
- 14 CONSTANT Modifiers
- 16 CONSTANT WhichWindow
-
-
- \ ===== Event Codes ======================================================
- DECIMAL
-
- 0 CONSTANT Null
- 1 CONSTANT MouseDown
- 2 CONSTANT MouseUp
- 3 CONSTANT KeyDown
- 4 CONSTANT KeyUp
- 5 CONSTANT AutoKey
- 6 CONSTANT UpdateEvent
- 7 CONSTANT DiskInserted
- 8 CONSTANT ActivateEvent
-
-
- \ ===== "FindWindow" result codes ========================================
- DECIMAL
-
- 0 CONSTANT InDesk
- 1 CONSTANT InMenuBar
- 2 CONSTANT InSysWindow
- 3 CONSTANT InContent
- 4 CONSTANT InDrag
- 5 CONSTANT InGrow
- 6 CONSTANT InGoAway
- 7 CONSTANT InZoomIn
- 8 CONSTANT InZoomOut
-
-
- \ ===== User variable offsets ============================================
- DECIMAL
-
- 40 CONSTANT HeadOffset
- 44 CONSTANT TailOffset
-
- 72 CONSTANT TaskWindowPointerOffset
- 108 CONSTANT TaskMenuBarOffset
- 116 CONSTANT MenuDataOffset
- 124 CONSTANT ControlDataOffset
- 128 CONSTANT ControlHandleOffset
- 136 CONSTANT DialogDataOffset
- 140 CONSTANT DialogHandleOffset
-
- 152 CONSTANT ContentOffset
- 156 CONSTANT DragOffset
- 160 CONSTANT GrowOffset
- 164 CONSTANT GoAwayOffset
- 168 CONSTANT UpdateOffset
- 172 CONSTANT ActivateOffset
- 190 CONSTANT DialogHookOffset
- 194 CONSTANT ZoomInOffset
- 198 CONSTANT ZoomOutOffset
- 202 CONSTANT ControlActionOffset
-
- \ ===== MultiFinder Constants ============================================
-
- 220 USER Next.Event.proc \ holds the vector for the Event proc
- 224 USER #.of.Null.Events \ word value to meter the number of Null Events
- 226 USER fgnd.bkgnd \ flag for Mach2 in foreground/background
-
- \ Suspend/Resume constants
-
- 1 CONSTANT Resume \ bit zero of EVENT-RECORD.what
-
-
- \ ===== Start of Code ====================================================
- \ ========================================================================
- \ ========================================================================
-
-
- \ ===== Utility Word =====================================================
-
- CODE ScreenRect ( - rectaddr )
- MOVE.L (A5),A0
- LEA screenBits(A0),A0
- LEA screenBounds(A0),A0
- MOVE.L A0,-(A6)
- RTS
- END-CODE
-
-
- \ ===== "Non-Vectorable" Default Event Handling Routines =================
-
- : Run-Desk ( - ) ;
-
- ( : Run-System ( - )
- ( we need to watch out here - if the click is in an inactive system
- window and the OPERATOR window is active, we need to re-enable the
- Edit Menu here. )
-
- CALL FrontWindow ( -- wptr )
- OPERATOR @ [ 2 TaskWindowPointerOffset + ] LITERAL + @ =
- IF
- EditHandle @
- ?DUP 0= NOT
- IF
- ( -- edithandle )
- 0 CALL EnableItem
- CALL DrawMenuBar
- THEN
- THEN
-
- EVENT-RECORD
- EVENT-RECORD WhichWindow + @
- CALL SystemClick
- ; )
-
- CODE Run-System
- EXG.L D4,A7 \ switch to trap stack
- SUBQ.L #4,A7 \ clear space for result
- _FrontWindow \ is the frontwindow the OPERATOR
- MOVE.L (A7)+,-(A6)
-
- MOVEA.L OPERATOR,A0 \ get the status address
- MOVE.L 2+TaskWindowPointerOffset(A0),-(A6) \ get the OPERATOR Window
-
- CMPM.L (A6)+,(A6)+ \ is the FrontWindow the OPERATOR
- BNE.S @callClick \ branch if not
-
- LEA NP,A0
- MOVE.L 14(A0),D0 \ get the EditHandle Edit Menu Handle
- TST.L D0 \ check to be sure it is a handle
- BEQ.S @callClick
-
- MOVE.L D0,-(A7) \ push the EditHandle
- CLR.W -(A7) \ Enable entire Menu
- _EnableItem \ enable the menu
- _DrawMenuBar \ update on the screen
-
- @callClick
- LEA "EVENT-RECORD",A0 \ get the event-record
- MOVE.L A0,-(A7) \ push it
- MOVE.L WhichWindow(A0),-(A7) \ get the window pointer
- _SystemClick \ let the system handle the event
- EXG.L D4,A7 \ switch back to task stack
- RTS
- END-CODE
-
-
- \ ===== Processing Menu Selections =======================================
-
- : Run-Menubar { | menudata wptr taskptr flag -- }
- EVENT-RECORD Where + @ CALL MenuSelect -> menudata
-
- \ MenuSelect will return zero in the high order word
- \ if no choice is made.
- ^ menudata W@
- IF
- CALL FrontWindow -> wptr
-
- BEGIN
- \ What kind of window is frontmost ?
- \ If it's a system window (a desk accessory window)
- \ look backwards through the linked list of windows
- \ for a window which belongs to a terminal task.
- wptr windowKind + W@ L_EXT 0<
-
- \ Also make sure we haven't reached the end
- \ of the window list.
- wptr 0 <>
- AND
- WHILE
- wptr nextWindow + @ -> wptr
- REPEAT
-
- \ Once we've found a valid window, one with a
- \ window kind greater than zero, we must make
- \ sure it is a terminal window.
- wptr CALL GetWRefCon -> taskptr
- taskptr
- IF
- \ If it is a terminal window we can
- \ send it the menu selection information.
- menudata taskptr MenuDataOffset + !
- THEN
- THEN
- ;
-
- ( CODE Run-MenuBar
- LEA EVENT-RECORD,A0
- EXG.L D4,A7
- MOVEQ.L #0,-(A7)
- MOVE.L Where(A0),-(A7)
- _MenuSelect
- MOVE.L (A7)+,-(A6)
- EXG.L D4,A7
-
- TST.W (A6)
- BEQ.S @getout
-
- @getout
- RTS
- END-CODE )
-
- ( : DoMenuKey { | menudata wptr taskptr flag -- flag }
- 0 -> flag
- EVENT-RECORD Message + 2+ W@ CALL MenuKey -> menudata
- ^ menudata W@
- IF
- CALL FrontWindow -> wptr
- wptr
- IF
- wptr CALL GetWRefCon -> taskptr
- taskptr
- IF
- taskptr TaskMenuBarOffset + @
- IF
- menudata taskptr MenuDataOffset + !
- -1 -> flag
- THEN
- THEN
- THEN
- THEN
- flag
- ; )
-
- CODE DoMenuKey
- LINK A2,#$-C
- MOVEQ.L #0,D0 \ store a false flag in menuFlag
- MOVE.L D0,$-C(A2)
-
- EXG.L D4,A7
- MOVE.L D0,-(A7) \ allocate space for result
- MOVE.W "EVENT-RECORD"+2+Message(A5),-(A7) \ get keyStroke
- _MenuKey
- MOVE.L (A7)+,$-4(A2) \ store result
-
- MOVE.W $-4(A2),D0 \ get menukey result
- BEQ.S @exitthis
-
- \ the key stroke was a menu key stroke
- SUBQ.L #4,A7
- _FrontWindow
- MOVE.L (A7)+,D0
- MOVE.L D0,$-8(A2)
- BEQ.S @exitthis
-
- SUBQ.L #4,A7
- MOVE.L D0,-(A7)
- _GetWRefCon
- MOVE.L (A7)+,A0
-
- BEQ.S @exitthis
-
- MOVE.L TaskMenuBarOffset(A0),D0
- BEQ.S @exitthis
-
- MOVE.L $-4(A2),MenuDataOffset(A0)
- MOVEQ.L #-1,D0
- MOVE.L D0,$-C(A2)
-
- @exitthis
- EXG.L D4,A7
- MOVE.L $-C(A2),-(A6)
- UNLK A2
- RTS
- END-CODE
-
- \ ===== Processing Key Input =============================================
- HEX
-
- ( : DoKey { | taskptr head tail temp1 temp2 -- }
- CALL FrontWindow
- CALL GetWRefCon -> taskptr
- taskptr
- IF
- taskptr HeadOffset + @ -> head
- taskptr TailOffset + @ -> tail
-
- head 4+ 3F AND -> temp1 \ Inc the head position
- head FFFFFFC0 AND -> temp2 \ Get base addr of queue.
- temp1 +> temp2 \ Form new head address.
-
- \ Would the queue overflow if we added a new
- \ character at the new head address ?
- \ (is the queue full?)
- temp2 tail <>
- IF
- \ Store modifiers information in upper
- \ word of local variable.
- EVENT-RECORD Modifiers + W@ ^ temp1 W!
-
- \ Store the key information in the lower
- \ word of local variable.
- EVENT-RECORD Message + 2+ W@ ^ temp1 2+ W!
-
- \ Enqueue the key data.
- temp1 head !
-
- \ Save the new head position.
- temp2 taskptr HeadOffset + !
- ELSE
- 5 CALL SysBEEP
- THEN
- ELSE
- 5 CALL SysBEEP
- THEN
- ; )
- DECIMAL
-
- CODE DoKey
- LINK A2,#$-14
- EXG.L D4,A7
- SUBQ.L #8,A7
- _FrontWindow
- _GetWRefCon
- MOVE.L (A7)+,A0 \ this should be the Taskptr
- EXG.L D4,A7
- MOVE.L A0,A0 \ is it zero
- BEQ.S @beepit
-
- MOVE.L A0,$-4(A2) \ save the taskptr
- MOVE.L HeadOffset(A0),$-8(A2) \ -> head
- MOVE.L TailOffset(A0),$-C(A2) \ -> tail
-
- MOVE.L $-8(A2),D0 \ head
- ADDQ.L #4,D0 \ 4+
- MOVEQ.L #$3F,D1
- AND.L D1,D0 \ $3F AND
- MOVE.L D0,$-10(A2) \ -> temp1
-
- MOVE.L $-8(A2),D1 \ head
- AND.L #$FFFFFFC0,D1 \ $FFFFFFC0 AND
- MOVE.L D1,$-14(A2) \ -> temp2
- ADD.L D0,$-14(A2) \ temp1 +> temp2
-
- \ Would the queue overflow if we added a new
- \ character at the new head address ?
- \ (is the queue full?)
- MOVE.L $-14(A2),D0 \ temp2
- MOVE.L $-C(A2),D1 \ tail
- CMP.L D1,D0
- BEQ.S @beepit
-
- MOVE.W "EVENT-RECORD"+Modifiers(A5),$-10(A2)
- MOVE.W "EVENT-RECORD"+Message+2(A5),$-E(A2)
- MOVE.L $-8(A2),A0 \ head
- MOVE.L $-10(A2),(A0) \ temp1
- MOVE.L $-4(A2),A0 \ taskPtr
- MOVE.L $-14(A2),HeadOffset(A0) \ temp2 taskptr HeadOffset + !
- BRA.S @exitthis
-
- @beepit
- EXG.L D4,A7
- MOVE.W #5,-(A7)
- _SysBeep
- EXG.L D4,A7
-
- @exitthis
- UNLK A2
- RTS
- END-CODE
-
- ( : DoKeyDown ( - )
- EVENT-RECORD Modifiers + W@ CommandKeyMask AND
- IF
- \ Handle a command key sequence.
- DoMenuKey 0=
- IF
- DoKey
- THEN
- ELSE
- \ Handle key input.
- DoKey
- THEN
- ; )
-
- CODE DoKeyDown
- MOVE.W "EVENT-RECORD"+Modifiers(A5),D0
- AND.W #CommandKeyMask,D0
- BEQ.S @normalKey
-
- JSR DoMenuKey
- TST.L (A6)+
- BNE.S @exitthis
-
- @normalKey
- JSR DoKey
-
- @exitthis
- RTS
- END-CODE
-
- \ ===== Processing Disk Events ===========================================
-
- : DoDisk ( - )
- CALL DILoad
- EVENT-RECORD Message + W@
- IF
- DiskPt
- EVENT-RECORD Message + @
- CALL DIBadMount
- DROP
- THEN
- CALL DIUnload
- ;
-
- \ ===== "Vectored" Event Handling Routines ===============================
- \ ===== (RUN-UPDATE) =====================================================
-
- ( : (RUN-UPDATE) { | saveport wptr -- }
- EVENT-RECORD Message + @ -> wptr
- ^ saveport CALL GetPort
- wptr CALL SetPort
-
- wptr CALL BeginUpdate
- wptr GrowFlagOffset + C@
- IF
- wptr VBarOffset + @
- wptr HBarOffset + @ OR
- 0=
- IF
- \ If there is just a growbox, set pen
- \ to PatBic mode before redrawing the
- \ grow icon. This will cause the grow
- \ box lines to remain invisible.
- PatBic CALL PenMode
- THEN
- wptr CALL DrawGrowIcon
- CALL PenNormal
- THEN
- wptr CALL DrawControls
- wptr CALL EndUpdate
- saveport CALL SetPort
- ; )
-
- CODE (RUN-UPDATE)
- MOVE.L A2,-(A7)
- MOVE.L "EVENT-RECORD"+Message(A5),A2
- SUBQ.L #4,A6
- EXG.L D4,A7
- MOVE.L A6,-(A7)
- _GetPort
- MOVE.L A2,-(A7)
- _SetPort
- MOVE.L A2,-(A7)
- _BeginUpdate
- MOVE.B GrowFlagOffset(A2),D0
- BEQ.S @drawcontrols
-
- MOVE.L VBarOffset(A2),D0
- OR.L HBarOffset(A2),D0
- BNE.S @drawGrowIcon
-
- MOVE.W #PatBic,-(A7)
- _PenMode
-
- @drawGrowIcon
- MOVE.L A2,-(A7)
- _DrawGrowIcon
- _PenNormal
-
- @drawcontrols
- MOVE.L A2,-(A7)
- _DrawControls
- MOVE.L A2,-(A7)
- _EndUpdate
- MOVE.L (A6)+,-(A7)
- _SetPort
- EXG.L D4,A7
- MOVE.L (A7)+,A2
- RTS
- END-CODE
-
- \ ===== (RUN-ACTIVATE) ===================================================
-
- : (RUN-ACTIVATE) { | wptr edith -- }
- EVENT-RECORD Message + @ -> wptr
-
- \ If Mach2 is around this EditHandle will hold
- \ the handle to the Mach2 "Edit" menu.
- EditHandle @ -> edith
-
- \ Check for an activate event.
- EVENT-RECORD Modifiers + W@ ActivateMask AND
- IF
- \ The edit menu should be disabled when the
- \ Mach window becomes the active window.
- edith
- IF
- wptr
- OPERATOR @ [ 2 TaskWindowPointerOffset + ] LITERAL + @ =
- IF
- \ 0 means disable entire menu.
- edith 0 CALL DisableItem
- OPERATOR @ ( -- OPER.STATUS )
- [ 2 TaskMenuBarOffset + ] LITERAL + @ @
- CALL SetMenuBar
- CALL DrawMenuBar
- THEN
- THEN
- THEN
- wptr CALL SetPort
- wptr GrowFlagOffset + C@
- IF
- wptr VBarOffset + @
- wptr HBarOffset + @ OR
- 0=
- IF
- \ If there is just a growbox, set pen
- \ to PatBic mode before redrawing the
- \ grow icon. This will cause the grow
- \ box lines to remain invisible.
- PatBic CALL PenMode
- THEN
- wptr CALL DrawGrowIcon
- CALL PenNormal
- THEN ;
-
-
- \ ===== "Vectored" Mouse Down Events =====================================
- \ ===== (CHECK-CONTROL) ==================================================
-
- : RunUserRoutine { wptr taskptr partcode chandle | address -- }
- taskptr ControlActionOffset + @ -> address
- address
- IF
- partcode
- chandle
- address EXECUTE
- THEN ;
-
- : MachTrackControl { wptr taskptr whichcontrol oldpartcode |
- point temppartcode -- flag }
- BEGIN
- CALL StillDown
- WHILE
- ^ point
- CALL GetMouse
-
- whichcontrol
- point
- CALL TestControl -> temppartcode
-
- temppartcode oldpartcode =
- IF
- whichcontrol
- temppartcode
- CALL HiliteControl
-
- wptr taskptr temppartcode whichcontrol
- RunUserRoutine
- ELSE
- whichcontrol
- 0
- CALL HiliteControl
- THEN
- REPEAT
- whichcontrol 0 CALL HiliteControl
-
- oldpartcode temppartcode =
- IF
- temppartcode
- ELSE
- 0
- THEN ;
-
- : MailData { chandle partcode taskptr -- }
- partcode taskptr ControlDataOffset + W!
- chandle taskptr ControlHandleOffset + ! ;
-
- : (CHECK-CONTROL) { wptr | saveport taskptr localpt whichcontrol partcode
- flag -- flag }
- 0 -> flag
- ^ saveport CALL GetPort
- wptr CALL SetPort
- wptr CALL GetWRefCon -> taskptr
- taskptr
- IF
- \ Look in the window record to see if this window
- \ has any controls.
- wptr controlList + @
- IF
- \ If this window has controls (1) convert the
- \ global mouse point coordinate found in the
- \ EVENT-RECORD to a local window mouse
- \ coordinate
- EVENT-RECORD Where + @ -> localpt
- ^ localpt CALL GlobalToLocal
-
- \ and (2) use FindControl to determine
- \ which control in the window experienced
- \ the interaction.
- localpt
- wptr
- ^ whichcontrol
- CALL FindControl -> partcode
-
- \ Check the value of the part code returned.
- \ If the mouse was pressed in an invisible,
- \ inactive, or no control, the part code will
- \ be zero. If the mouse was pressed in a
- \ visible, active control the part code will
- \ be a valid, non-zero part code value.
- partcode
- IF
- \ The mouse was clicked in a valid
- \ control, now follow the mouse to
- \ see if it was released in the control.
- -1 -> flag
- partcode InThumb =
- IF
- whichcontrol
- localpt
- 0
- CALL TrackControl -> partcode
- ELSE
- wptr
- taskptr
- whichcontrol
- partcode
- MachTrackControl -> partcode
- THEN
-
- \ Send the control interaction data
- \ to the task.
- whichcontrol partcode taskptr MailData
- THEN
- THEN
- THEN
- saveport CALL SetPort
- flag ;
-
-
- \ ===== (RUN-CONTENT) ====================================================
-
- : (RUN-CONTENT) { | wptr taskptr menulist -- }
- \ Is the window clicked in the active window ?
- EVENT-RECORD WhichWindow + @ -> wptr
- CALL FrontWindow wptr <>
- IF
- \ Initialize local variable.
- EmptyMenuBar @ -> menulist
-
- \ This window was not active, select it.
- wptr CALL SelectWindow
-
- \ If the window just selected has a
- \ menubar, display the menubar.
- \ Otherwise display and empty menubar.
- wptr CALL GetWRefCon -> taskptr
- taskptr
- IF
- \ Check the TaskMenuBar field of the
- \ task's user variable area. A non-zero
- \ value found there should be the address
- \ where the MenuList handle for the task's
- \ menubar is stored.
- taskptr TaskMenubarOffset + @
- ?DUP
- IF
- \ Display the task's custom menubar.
- @ -> menulist
- THEN
- THEN
- menulist CALL SetMenuBar
- CALL DrawMenuBar
- ELSE
- wptr (CHECK-CONTROL) DROP
- THEN ;
-
-
- \ ===== (RUN-DRAG) =======================================================
-
- : (RUN-DRAG) { | wptr taskptr -- }
- \ Check to see if the window whose drag region was clicked in
- \ is the current active window
- EVENT-RECORD WhichWindow + @ -> wptr
-
- CALL FrontWindow
- wptr
- <>
- IF
- \ If the window clicked in was not the active window
- \ first check to see if the command key was held down
- \ when the click occurred. If it was, we will not
- \ activate the window.
- EVENT-RECORD Modifiers + W@ CommandKeyMask AND
- 0=
- IF
- \ The command key was not down,
- \ select the window.
- wptr CALL SelectWindow
-
- \ If the window just selected has a
- \ menubar, display the menubar.
- \ Otherwise display and empty menubar.
- wptr CALL GetWRefCon -> taskptr
- taskptr
- IF
- \ Check the TaskMenuBar field of the
- \ task's user variable area. A non-zero
- \ value found there should be the address
- \ where the MenuList handle for the task's
- \ menubar is stored.
- taskptr TaskMenubarOffset + @
- DUP
- IF
- \ Display the task's custom menubar.
- @ CALL SetMenubar
- ELSE
- \ Display an empty menubar.
- DROP ( the zero TaskMenuBar)
- EmptyMenubar @ CALL SetMenubar
- THEN
- CALL DrawMenuBar
- THEN
- THEN
- THEN
- wptr \ Windowpointer for window to drag.
- EVENT-RECORD Where + @ \ Mouse location in global coordinates.
- ScreenRect \ Coordinates of this screen.
- CALL DragWindow ;
-
-
- \ ===== (RUN-GROWBOX) ====================================================
-
- : RedrawHVBars { wptr | vbarh hbarh -- }
- wptr VBarOffset + @ -> vbarh
- wptr HBarOffset + @ -> hbarh
-
- vbarh
- IF
- \ Hide the control before we redraw it.
- vbarh CALL HideControl
-
- \ Move the control to its new position.
- vbarh
- wptr portRect + 6 + W@ 15 - \ Horizontal destination.
- wptr portRect + W@ 1- \ Vertical destination.
- CALL MoveControl
-
- \ Resize the control
- vbarh
- 16 \ New control width.
- wptr portRect + 4+ W@ 13 - \ New control height.
- CALL SizeControl
-
- \ Now tell the window manager that the control
- \ area has already been redrawn
- vbarh @ ctrlRectOffset +
- CALL ValidRect
-
- \ Now the control can be made visible again.
- vbarh CALL ShowControl
- THEN
-
- hbarh
- IF
- hbarh CALL HideControl
-
- hbarh
- wptr portRect + 2+ W@ 1- \ Horiz. dest.
- wptr portRect + 4+ W@ 15 - \ Vert. dest.
- CALL MoveControl
-
- hbarh
- wptr portRect + 6 + W@ 13 - \ New width.
- 16 \ New height.
- CALL SizeControl
-
- hbarh @ ctrlRectOffset +
- CALL ValidRect
-
- hbarh CALL ShowControl
- THEN ;
-
- : EraseEdges { wptr | oldbot oldright rightbot lefttop -- }
- ^ lefttop ^ rightbot 2DROP
- wptr portRect + 4+ W@ -> oldbot
- wptr portRect + 6 + w@ -> oldright
-
- \ First, erase bottom edge of window.
- oldbot 16 - ^ lefttop W! \ Top of rect to be erased.
- 0 ^ lefttop 2+ W! \ Left of rect to be erased.
- oldbot ^ rightbot W! \ Bot. of rect to be erased.
- oldright ^ rightbot 2+ W! \ Right of rect to be erased.
- ^ lefttop CALL EraseRect
- ^ lefttop CALL InvalRect
-
- \ Next, erase right edge of window.
- 0 ^ lefttop W!
- oldright 16 - ^ lefttop 2+ W!
- oldbot ^ rightbot W!
- oldright ^ rightbot 2+ W!
- ^ lefttop CALL EraseRect
- ^ lefttop CALL InvalRect ;
-
- : (RUN-GROWBOX) { | wptr wrect oldheight
- rightbot lefttop newwidth newheight -- }
- EVENT-RECORD WhichWindow + @ -> wptr
- CALL FrontWindow wptr =
- IF
- wptr portRect + -> wrect
- wrect 4+ W@ wrect W@ - -> oldheight
- ScreenRect ^ lefttop 8 CMOVE
-
- wptr CALL SetPort
- wptr
- EVENT-RECORD Where + @
- ^ lefttop
- CALL GrowWindow -> newwidth
- ^ newwidth W@ -> newheight
- 0 ^ newwidth W!
-
- \ Is the window shorter ?
- newheight oldheight <
- IF
- wrect CALL InvalRect
- wrect CALL EraseRect
- THEN
-
- wptr EraseEdges
- wptr newwidth newheight -1 CALL SizeWindow
- wptr EraseEdges
-
- wptr RedrawHVBars
- THEN ;
-
-
- \ ===== (RUN-CLOSEBOX) ===================================================
-
- : (RUN-CLOSEBOX) { | wptr menuhandle taskptr -- }
- \ If the window is not the active window, leave.
- EVENT-RECORD WhichWindow + @ -> wptr
- CALL FrontWindow wptr =
- IF
- \ Initialize the contents of the menulist local variable.
- EmptyMenubar @ -> menuhandle
-
- \ Follow the mouse.
- \ If it is not released inside of the close box, leave.
- wptr
- EVENT-RECORD Where + @
- CALL TrackGoAway
- IF
- \ Hide the window and get the window
- \ pointer for the window immediately behind
- \ the window just closed, if any.
- wptr CALL HideWindow
- CALL FrontWindow -> wptr
- wptr
- IF
- \ If the window just uncovered has a
- \ menubar, display the menubar.
- \ Otherwise display and empty menubar.
- wptr CALL GetWRefCon -> taskptr
- taskptr
- IF
- \ Check the TaskMenuBar field of
- \ the task's user variable area.
- \ A non-zero value found there
- \ should be the address where the
- \ MenuList handle for the task's
- \ menubar is stored.
- taskptr TaskMenubarOffset + @
- ?DUP
- IF
- \ Display the task's
- \ custom menubar.
- @ -> menuhandle
- THEN
- THEN
- THEN
- menuhandle CALL SetMenuBar
- CALL DrawMenubar
- THEN
- THEN ;
-
-
- \ ===== (RUN-ZOOMIN) =====================================================
- \ ===== (RUN-ZOOMOUT) ====================================================
-
- : DoZoom { findcode | wptr taskptr -- }
- EVENT-RECORD WhichWindow + @ -> wptr
- CALL FrontWindow wptr =
- IF
- wptr CALL SetPort
-
- wptr
- EVENT-RECORD Where + @
- findcode
- CALL TrackBox
- IF
- wptr EraseEdges
-
- wptr findcode -1 CALL ZoomWindow
-
- wptr EraseEdges
- wptr RedrawHVBars
- THEN
- THEN ;
-
- : (RUN-ZOOMIN) ( - )
- InZoomIn DoZoom ;
-
- : (RUN-ZOOMOUT) ( - )
- InZoomOut DoZoom ;
-
-
- \ ===== MouseDown Event Dispatch Routine =================================
-
- : DoMouseDown { | findcode window taskptr -- }
- EVENT-RECORD Where + @
- ^ window
- CALL FindWindow -> findcode
-
- \ If click is in the menubar, we must specifically check for
- \ the frontwindow.
- findcode InMenuBar =
- IF
- CALL FrontWindow -> window
- THEN
-
- \ If click is in the growbox area, make sure the window has a
- \ growbox. If it doesn't, turn click into an in-content code.
- findcode InGrow =
- IF
- window GrowFlagOffset + C@ 0=
- IF
- InContent -> findcode
- THEN
- THEN
-
- \ We will only process this event if we have a valid windowpointer.
- window
- IF
- window EVENT-RECORD WhichWindow + !
- window CALL GetWRefCon -> taskptr
- taskptr
- IF
- findcode
- CASE
- InContent
- OF taskptr ContentOffset + @ EXECUTE
- ENDOF
-
- InDrag
- OF taskptr DragOffset + @ EXECUTE
- ENDOF
-
- InGrow
- OF taskptr GrowOffset + @ EXECUTE
- ENDOF
-
- InGoAway
- OF taskptr GoAwayOffset + @ EXECUTE
- ENDOF
-
- InZoomIn
- OF taskptr ZoomInOffset + @ EXECUTE
- ENDOF
-
- InZoomOut
- OF taskptr ZoomOutOffset + @ EXECUTE
- ENDOF
-
- InSysWindow OF Run-System ENDOF
- InMenuBar OF Run-Menubar ENDOF
- InDesk OF Run-Desk ENDOF
- ENDCASE
- ELSE
- findcode
- CASE
- InContent OF (RUN-CONTENT) ENDOF
- InDrag OF (RUN-DRAG) ENDOF
- InGrow OF (RUN-GROWBOX) ENDOF
- InGoAway OF (RUN-CLOSEBOX) ENDOF
- InZoomIn OF (RUN-ZOOMIN) ENDOF
- InZoomOut OF (RUN-ZOOMOUT) ENDOF
-
- InSysWindow OF Run-System ENDOF
- InMenuBar OF Run-Menubar ENDOF
- InDesk OF Run-Desk ENDOF
- ENDCASE
- THEN
- THEN ;
-
-
- \ ===== Modeless Dialog Event Dispatch Routine ===========================
- \ ===== (HandleDialog) ===================================================
-
- : (HandleDialog) { | thedialog itemhit wptr taskptr -- }
- \ This routine is called if a modeless dialog event has occurred.
- \ We know it is a modeless dialog event because a modal dialog
- \ would use its own event loop.
- \ If the event involves an enabled dialog item, DialogSelect
- \ will return TRUE and will return the dialog handle and
- \ the item number affected in the specified local variables.
- EVENT-RECORD ^ thedialog ^ itemhit CALL DialogSelect
- IF
- \ Which terminal task is using this modeless dialog ?
- CALL FrontWindow -> wptr
- wptr
- IF
- wptr CALL GetWRefCon -> taskptr
- taskptr
- IF
- \ If we were able to find the taskptr
- \ we can place the important information
- \ about the modeless dialog interaction
- \ in the appropriate user variable fields
- \ of the task's user variable area.
-
- \ The item number is a word length value.
- \ It will be returned in the upper 2 bytes
- \ of the local variable.
- ^ itemhit W@
- taskptr DialogDataOffset +
- W!
-
- thedialog
- taskptr DialogHandleOffset +
- !
- THEN
- THEN
- THEN ;
-
-
- \ ===== Event Dispatching Routines =======================================
-
- : HandleDialog { | taskptr wptr eventWhat exitflag -- }
- \ If it's a dialog event (and not an activate or update), the Message field of
- \ the EVENT-RECORD will not contain a window pointer, we must
- \ specifically ask for the window pointer.
- EVENT-RECORD What + W@ -> eventWhat
- eventWhat ActivateEvent = eventWhat UpdateEvent = OR
- IF
- EVENT-RECORD Message + @ -> wptr
- ELSE
- CALL FrontWindow -> wptr
- THEN
- BEGIN
- wptr WindowKind + W@
- dialogKind =
- IF
- wptr CALL GetWRefCon -> taskptr
- taskptr
- IF
- ( let the task call DialogSelect using it's own routine
- in DialogHook )
- taskptr DialogHookOffset + @ EXECUTE
- ELSE
- ( do the default dialog handling routine )
- (HandleDialog)
- THEN
- .TRUE. -> exitflag
- ELSE
- wptr NextWindow + @ -> wptr
- wptr 0=
- IF
- ( we have run out of windows, call the default
- routine and exit. )
- .TRUE. -> exitflag
- (HandleDialog)
- ELSE
- .FALSE. -> exitflag
- THEN
- THEN
-
- exitflag
- UNTIL
- ;
-
- : DoUpdate { | taskptr -- }
- EVENT-RECORD Message + @ CALL GetWRefCon -> taskptr
- taskptr
- IF
- taskptr UpdateOffset + @ EXECUTE
- ELSE
- (RUN-UPDATE)
- THEN ;
-
- : DoActivate { | taskptr -- }
- EVENT-RECORD Message + @ CALL GetWRefCon -> taskptr
- taskptr
- IF
- taskptr ActivateOffset + @ EXECUTE
- ELSE
- (RUN-ACTIVATE)
- THEN ;
-
- : NextEvent ( - ) ;
-
-
- \ ===== MultiFinder Event Handling Code =================================
-
- CODE Next.Event
- LEA 2(PC),A0 \ the actual offset will be filled in later
- MOVE.L A0,-(A7)
- RTS
- END-CODE
-
- : GetNextEvent
- CALL SystemTask
- EveryEvent EVENT-RECORD CALL GetNextEvent
- ;
-
- : WaitNextEvent
- { | mysleep -- result }
- EVENT-RECORD W@ 0=
- IF
- ( the last event was a Null Event, so get another -
- use the value in #.of.Null.Events to set the
- sleep parameter)
- #.of.Null.Events W@ DUP
- L_EXT -1 + ABS #.of.Null.Events W! ( toggle between zero and one )
- ELSE
- ( the event is non-null, so set the sleep parameter to zero,
- and reset the #.of.Null.Events parameter )
- 0 DUP #.of.Null.Events W!
- THEN
- -> mysleep
- EveryEvent EVENT-RECORD mysleep 0 CALL WaitNextEvent
- ;
-
- : All.Events
- Next.Event.proc @ EXECUTE \ get routine from USER variable
- ;
-
- ( Now we need the startup code )
-
- : First.Event
- ( This routine establishes whether MultiFinder is running
- and sets the correct Event get vector )
-
- MACH2.flags @ $08 AND 0=
- IF
- ( MultiFinder doesn't exist )
- ['] GetNextEvent
- ELSE
- 0 #.of.Null.Events W! ( set the null events toggle )
- ['] WaitNextEvent
- THEN
- Next.Event.proc ! ( stored in USER variable )
-
- ( now set the vector execution path )
- ['] All.Events ['] Next.Event 2+ -
- ['] Next.Event 2+ W!
- ( and call it )
- Next.Event
- ;
-
- ' First.Event
- ' Next.Event 2+ -
- ' Next.Event 2+ W!
-
- ( Now set up here for Suspend/Resume Events )
-
- : do.Suspend.Resume
- { | taskptr windowPtr the.windowKind -- }
- EVENT-RECORD Message + @ Resume AND
- fgnd.bkgnd W!
-
- CALL FrontWindow -> windowPtr
- windowPtr
- IF
- ( first simulate an activate/deactivate event )
- ActivateEvent EVENT-RECORD W!
- windowPtr EVENT-RECORD Message + !
- fgnd.bkgnd W@ EVENT-RECORD Modifiers + W!
-
- windowPtr windowKind + W@ L_EXT -> the.windowKind
-
- windowPtr CALL GetWRefCon -> taskptr
-
- the.windowKind 7 >
- taskptr
- AND
- IF
- \ it is definitely a program window
- taskptr ActivateOffset + @ EXECUTE
- ELSE
- the.windowKind 0<
- IF
- \ it is a desk accessory
- EVENT-RECORD CALL SystemEvent
- DROP ( the result )
- ELSE
- \ the only thing left is a dialog or alert, and it should
- \ be modeless
- HandleDialog
- THEN
- THEN
- THEN
- ;
-
- \ ===== High-Level Events ================================================
-
- CODE do.AEvent
- MOVEM.L D5-D7/A2/A3/A7,-(A6) \ push the task State because the
- MOVE.L A6,8(A4) \ AE handler always switches back in
- EXG.L D4,A7 \ switch to the trapStack
- SUBQ.L #2,A7 \ space for result
- LEA "EVENT-RECORD",A0 \ get the Event record
- MOVE.L A0,-(A7) \ push on the stack
- MOVE.W #$021B,D0 \ selector for trap
- _AEProcessAppleEvent
- ADDQ.L #2,A7 \ drop the result, because there
- EXG.L D4,A7 \ is nobody to pass it to
- MOVE.L 8(A4),A6 \ restore the stack
- MOVEM.L (A6)+,D5-D7/A2/A3/A7 \ restore the registers
- RTS
- END-CODE
-
- : Do.HLE
- \ CALL Debugger
- HLE.Handler @ ?DUP 0= NOT
- IF
- 0 SWAP EXECUTE ( result -- result )
- ( result is zero if HLE.handler couldn't handle this event,
- and non-zero if it did )
- 0=
- IF
- do.AEvent
- THEN
- ELSE
- do.AEvent
- THEN
- PAUSE
- ;
-
- \ ===== (EVENT-TABLE =====================================================
-
- CREATE (EVENT-TABLE)
- DC.L NextEvent-"(EVENT-TABLE)"-4 \ (0) Null event.
- DC.L "DoMouseDown"-"(EVENT-TABLE)"-4 \ (1) Mouse down event.
- DC.L NextEvent-"(EVENT-TABLE)"-4 \ (2) Mouse up event.
- DC.L "DoKeyDown"-"(EVENT-TABLE)"-4 \ (3) Key down event.
- DC.L NextEvent-"(EVENT-TABLE)"-4 \ (4) Key up event.
- DC.L "DoKeyDown"-"(EVENT-TABLE)"-4 \ (5) Auto key event.
- DC.L "DoUpdate"-"(EVENT-TABLE)"-4 \ (6) Update event.
- DC.L "DoDisk"-"(EVENT-TABLE)"-4 \ (7) Disk event.
- DC.L "DoActivate"-"(EVENT-TABLE)"-4 \ (8) Activate event.
- DC.L NextEvent-"(EVENT-TABLE)"-4 \ (9) Not used ?
- DC.L NextEvent-"(EVENT-TABLE)"-4 \ (10) Network event.
- DC.L NextEvent-"(EVENT-TABLE)"-4 \ (11) Driver event.
- DC.L NextEvent-"(EVENT-TABLE)"-4 \ (12) Appl-defined event #1.
- DC.L NextEvent-"(EVENT-TABLE)"-4 \ (13) Appl-defined event #2.
- DC.L NextEvent-"(EVENT-TABLE)"-4 \ (14) Appl-defined event #3.
- DC.L "do.Suspend.Resume"-"(EVENT-TABLE)"-4 \ (15) Suspend/Resume Events.
- DC.L NextEvent-"(EVENT-TABLE)"-4 \ (16) Not used ?
- DC.L NextEvent-"(EVENT-TABLE)"-4 \ (17) Not used ?
- DC.L NextEvent-"(EVENT-TABLE)"-4 \ (18) Not used ?
- DC.L NextEvent-"(EVENT-TABLE)"-4 \ (19) Not used ?
- DC.L NextEvent-"(EVENT-TABLE)"-4 \ (20) Not used ?
- DC.L NextEvent-"(EVENT-TABLE)"-4 \ (21) Not used ?
- DC.L NextEvent-"(EVENT-TABLE)"-4 \ (22) Not used ?
- DC.L "Do.HLE"-"(EVENT-TABLE)"-4 \ (23) High-level event
-
-
- ( : HandleEvent { | eventcode baseaddr -- }
- EVENT-RECORD What + W@ -> eventcode
- (EVENT-TABLE) -> baseaddr
- baseaddr \ Base address.
- eventcode 4* \ Index into event table.
- + @ \ Offset to routine.
- baseaddr + \ Address of routine.
- EXECUTE
- ; )
-
- CODE HandleEvent
- MOVE.W "EVENT-RECORD",D0
- ASL.W #2,D0 \ multiply event code by 4
- LEA "(EVENT-TABLE)"+4,A0 \ get base address of event table entries
- MOVE.L (A0,D0.W),D0 \ get offset from base of event table
- JSR (A0,D0.L) \ add offset to event table base and JSR to it
- RTS
- END-CODE
-
- \ ===== The Main Loop ====================================================
-
- : DialogEvent? ( - f )
- \ If the event is a dialog event which should be handled
- \ by our application (usually be being passed to DialogSelect),
- \ IsDialogEvent will return a true flag. If the event
- \ should be handled as a normal, non-dialog event, false
- \ will be returned.
- EVENT-RECORD CALL IsDialogEvent ;
-
- \ ===== (IOTASK) =========================================================
-
- : (IOTask) { | dialogflag eventflag -- }
- BEGIN
- BEGIN
- Next.Event -> eventflag
- DialogEvent? -> dialogflag
-
- dialogflag
- IF
- HandleDialog
- ELSE
- eventflag
- IF
- HandleEvent
- THEN
- THEN
- eventflag 0=
- UNTIL
- PAUSE
- AGAIN ;
-
- ONLY FORTH
-
- NEW-IOTASK
-
- \ ===== END OF FILE ======================================================
- \ ========================================================================
- \ ========================================================================
-